/*
 * Log_Monitor.cpp
 *
 *  Created on: Aug 26, 2010
 */

#include "Log_Monitor.h"
#include "SplashScreen.h"
#include "NamedDataBase.h"
#include "FileLogger.h"

_LIT(KVoiceCallDescription, "Voice call");
_LIT(KVideoCallDescription, "Video call");
_LIT(KIncoming, "Incoming");
_LIT(KOutgoing, "Outgoing");
_LIT(KMissed, "Missed call");

CLogMonitor* CLogMonitor::NewL(MLogMonitor* aCallBack)
{
    CLogMonitor* self = CLogMonitor::NewLC(aCallBack);
    CleanupStack::Pop(self);
    return self;
}
 
CLogMonitor* CLogMonitor::NewLC(MLogMonitor* aCallBack)
{
    CLogMonitor* self = new (ELeave) CLogMonitor(aCallBack);
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
}
 
CLogMonitor::CLogMonitor(MLogMonitor* aCallBack)
:CActive(0),iState(EUninitalised),iCallBack(aCallBack)
{
}
 
CLogMonitor::~CLogMonitor()
{
    Cancel();
 
    delete iRecentLogView, iRecentLogView = NULL;
    delete iLogClient, iLogClient = NULL;
 
    iFsSession.Close();
}
 
void CLogMonitor::ConstructL()
{	
    CActiveScheduler::Add(this);
 
    User::LeaveIfError(iFsSession.Connect());
 
    iLogClient = CLogClient::NewL(iFsSession);
    iRecentLogView = CLogViewRecent::NewL(*iLogClient);	
 
    iState = EInitalised;
    
    // initialising the Database
    iDb = new(ELeave) CMyDBClass;
    
    iFileLogger = new(ELeave) FileLogger;
    
    lastLogEventId = -1;	// temporarily assigning -1
    
    // finding out the Id of last log event.
    StartFindingLastEventId();
}
 
void CLogMonitor::DoCancel()
{
    if(iRecentLogView)
    {
        iRecentLogView->Cancel();
    }
    if(iLogClient)
    {
        if(iState == EWaitingChange)
        {
			iLogClient->NotifyChangeCancel();
       	}
        else
        {
			iLogClient->Cancel();
        }
    }
}
 
void CLogMonitor::RunL()
{
    if(iStatus != KErrCancel)
    {
        switch(iState)
        {        		
        	case EFindingLastLogEventId:
        		if(iRecentLogView)
        		{
					TInt count = iRecentLogView->CountL();
					if(count > 0)
					{
						GetLastEventId();
					}
					else
					{
						StartMonitorL();
					}
        		}
        		break;
        		
        	case EReadingLastLogEventId:
        		if(iStatus == KErrNone && iRecentLogView)
				{
					const CLogEvent& logEvent = iRecentLogView->Event();
					lastLogEventId = logEvent.Id();										
				}
        		StartMonitorL();
        		break;
        		
            case EWaitingChange:
				//User::After(1000000);
				GetLatest();
                break;
 
            case EReadingLog:
                if(iRecentLogView)
                {
                    if(iRecentLogView->CountL() > 0)
                    {
						GetFirstEventL();
                    }
                    else
                    {
						StartMonitorL();
                    }
                }
                break;
 
            case EReadingLogItems:
            	StartMonitorL();
            	break;
            	
            case EReadingFirstLog:
            
                if(iStatus == KErrNone && iRecentLogView)
                {
					const CLogEvent& logEvent = iRecentLogView->Event();
					
					if(logEvent.Id() > lastLogEventId)
					{
						if(logEvent.Duration() > 0)
						{
							lastLogEventId = logEvent.Id();
							
							// executing callback function
							iCallBack->LogEventL(logEvent, iDb, iFileLogger);
							
							//GetNextEventL();
						}
					}
                }
                StartMonitorL();	
                break;
                      	
 
            case EDeletingEvent:
                //GetNextEventL();	
                break;
 
            default:
                StartMonitorL();
                break;
        }
    }
}	

void CLogMonitor::StartFindingLastEventId()
{
	if(iRecentLogView)
	{		
		iState = EFindingLastLogEventId;
		iRecentLogView->Cancel();

		if(iRecentLogView->SetRecentListL(KLogNullRecentList,iStatus))
		{
			SetActive();
		}
		else
		{
			StartMonitorL();
		}
	}
}

void CLogMonitor::GetLastEventId()
{
	if(iRecentLogView)
	{
		iState = EReadingLastLogEventId;

		if(iRecentLogView->FirstL(iStatus))
		{
			SetActive();
		}
		else
		{
			StartMonitorL();
		}
	}
}
 
void CLogMonitor::StartMonitorL()
{
    if(iLogClient)
    {
        if(iRecentLogView)
        {
			iRecentLogView->Cancel();
        }
 
        iLogClient->Cancel();
 
        iState = EWaitingChange;
        iLogClient->NotifyChange(TTimeIntervalMicroSeconds32(3000000),iStatus);
        SetActive();
    }
}
 
void CLogMonitor::GetLatest()
{
    if(iRecentLogView)
    {		
        iState = EReadingLog;
        iRecentLogView->Cancel();

        if(iRecentLogView->SetRecentListL(KLogNullRecentList,iStatus))
        {
			SetActive();
        }
        else
        {
			StartMonitorL();
        }
    }
}
 
void CLogMonitor::GetFirstEventL()
{
    if(iRecentLogView)
    {
        iState = EReadingFirstLog;

        if(iRecentLogView->FirstL(iStatus))
        {
			SetActive();
        }
        else
        {
			StartMonitorL();
        }
    }
}
 
void CLogMonitor::GetNextEventL()
{
    if(iRecentLogView)
    {	
        iState = EReadingLogItems;

        if(iRecentLogView->PreviousL(iStatus))
        {
			SetActive();
        }
        else
        {
			StartMonitorL();
        }
     }
}


// MLogMonitor class fucntions
void MLogMonitor::LogEventL(const CLogEvent& event, CMyDBClass* iDb, FileLogger* iFileLogger)
{
	// if it is (a Voice OR Video call) AND (NOT a Missed call)
	if ((event.Description() == KVoiceCallDescription || event.Description() == KVideoCallDescription) && (event.Direction() != KMissed))
	{	
	/*----- Call Details -----*/
	/*
_LIT(NCol2,"RemoteNumber");	// Phone number of Remote party
_LIT(NCol3,"StartTime");	// Format: hh:mm:ss
_LIT(NCol4,"Direction");	// whether Incoming="0" OR Outgoing="1"
_LIT(NCol5,"Type");			// whether Voice="0" OR Video="1"
_LIT(NCol6,"Duration");		// Duration in seconds. Datatype: EDbColUint32
_LIT(NCol7,"Date");			// Format: dd/MM/yyyy
	 */
	
	TTime time = event.Time();
	time.HomeTime();
	TDateTime dt;
	dt = time.DateTime();

	// Event ID
	TLogId eventId = event.Id();
	
	// My Number
	TBuf<KLogMaxNumberLength> myNumber;	// ------------- TO-DO --------------
	/* temporarily */ myNumber.Append(_L("0")); 
	
	// Remote Party Number
	TBuf<KLogMaxNumberLength> remoteNumber = event.Number();
	
	// Start Time. Format is hh:mm:ss
	TBuf<9> startTime;
	startTime.Format(_L("%02d:%02d:%02d"), dt.Hour(), dt.Minute(), dt.Second());
	
	// Direction: whether Incoming OR Outgoing OR Missed...
	TBuf<2> direction;
	if(event.Direction() == KIncoming)	// For an "Incoming" call
	{
		direction.Append(_L("0"));
	}
	else if(event.Direction() == KOutgoing)	// For an "Outgoing" call
	{
		direction.Append(_L("1"));
	}
	else	// if the Direction is some other
	{
		direction.Append(_L("2"));
	}
	
	// Call Type Description: whether Voice OR Video...
	TBuf<2> type;
	if(event.Description() == KVoiceCallDescription)	// For "Voice call"
	{
		type.Append(_L("0"));
	}
	else if(event.Description() == KVideoCallDescription)	// For "Video call"
	{
		type.Append(_L("1"));
	}

	// Duration in seconds
	TLogDuration duration = event.Duration();

	// Date. Format is yyyy/MM/dd
	TBuf<11> date;
	date.Format(_L("%04d/%02d/%02d"), dt.Year(), dt.Month()+1, dt.Day()+1);
	
	
	// Inserting the Call Details into the Database
	iDb->SaveToDatabaseL(myNumber, remoteNumber, startTime, direction, type, duration, date);
	
	
	// Log Entry format is:
	// ddMMyyyy,hhmmss,0777123456,0777123456,0,i,hhmmss
	// [date, time, my number, other party number, whether voice(0) or video(1), whether incoming(i) or outgoing (o ), duration]
	
	TBuf<500> logEntry;	
	logEntry.Format(_L("%d-%d-%d,%d:%d:%d,"), dt.Day()+1, dt.Month()+1, dt.Year(),dt.Hour(),dt.Minute(),dt.Second());
	
	logEntry.AppendNum(eventId);   // Event ID
	logEntry.Append(_L(","));
			
	logEntry.Append(remoteNumber);  // phone number of other party
	logEntry.Append(_L(","));
	
	logEntry.Append(type);	// whether "Voice call"=0 OR "Video call"=1
	logEntry.Append(_L(","));
		
	if(direction == (_L("0")))  // if it is an "Incoming" call
	{
		logEntry.Append(_L("in"));
	}
	else if(direction == (_L("1")))  // if it is an "Outgoing" call
	{
		logEntry.Append(_L("out"));
	}
	else	// if not "Incoming" or "Outgoing"
	{
		logEntry.Append(direction);
	}
	logEntry.Append(_L(","));
	
	logEntry.AppendNum(duration);  // duration in seconds
	
	iFileLogger->AddLog(logEntry);
	}														  
}
